<?php

class SiteUser extends DBSiteUser {

	/**
	 * Típus konstans. Ez egy tök normál személy.
	 * @var int
	 */
	const TYPE_NORMAL = 1;

	/**
	 * Típus konstans. Ez egy új, még fejezetlen személy regisztráció.
	 * @var int
	 */
	const TYPE_NEWREG = 3;


	/**
	 * A jogok között összefüggések vannak. Ez a mező már az összefüggések figyelembe vételével tartalmazza a jogmaszkot!
	 * @var int
	 */
	private $_calcRights;

	public function SiteUser() {
		parent::DBSiteUser();
	}


	/**
	 * Visszaadja az ember valós nevét - a nyelv szerint normálisan
	 *
	 * @param string $langcode melyik nyelvkóddal? ha nincs megadva, akkor az aktuális lesz
	 * @return string
	 */
	public function getRealName($langcode = null) {
		return $this->getName();
	}

	/**
	 * Visszaadja a user login nevét.
	 * Ha van konkrét userneve, akkor azt, ha nincs akkor az e-mail címét
	 *
	 * @return string
	 */
	public function getLoginName() {
		return $this->email;
	}


	/**
	 * Visszaadja a csávó nyelvi preferenciáját. Ez nyelvkódok tömbje, minél hamarabb van
	 * benne egy nyelvkód, annál inkább szeretné abban kapni a dolgokat!
	 *
	 * Ezt a metódust akkor kell használni, ha a belépett user, és ez a user kurvára
	 * nem ugyanaz! Pl. ennek a usernek e-mail-t akarunk küldeni, amit az amúgy belépett
	 * admin user valamelyik művelete vált ki.
	 *
	 * @return array
	 */
	public function getLanguagePreference() {
			
		$pref = array();
			
		$siteId = SiteHandler::getCurrentSiteId();
		$langcode = SiteHandler::getDefaultLangcodeOfSite($siteId);
		if(!is_null($langcode))
		array_push($pref, $langcode);

		$pref = FunctionLibrary::arrayConcatenate($pref, SiteHandler::getLanguageCodesOfSite($siteId));
			
		return $pref;
	}


	/**
	 * Csinál egy e-mail-hez használható AlertRecipient objektumot ehhez a személyhez
	 * @return AlertRecipient
	 */
	public function toEmailAlertRecipient() {

		$rec = new AlertRecipient();
		$rec->sendHere = $this->email;
		$rec->langcodes = $this->getLanguagePreference();
			
		$vars = array(
			"password" => $this->password,
			"loginName" => $this->getLoginName(),
			"name" => $this->getRealName(),
		);

		$rec->variables = $vars;
			
		return $rec;
	}

	/**
	 * Megadja, hogy a csávó milyen nyelvkódok közül válogathat.
	 * sysadmin bármi ami van, többiek csak saját site
	 *
	 * @return array
	 */
	public function getAvailableLangcodes() {			
		return SiteHandler::getLanguageCodesOfSite($this->siteId);
	}


	/**
	 * Combo-boxra megadja, hogy a csávó milyen nyelvkódok közül válogathat.
	 * sysadmin bármi ami van, többiek csak saját site
	 *
	 * @return array
	 */
	public function getAvailableLanguagesForCombo() {			
		$siteLangs = SiteHandler::getLanguagesOfSiteForCombo($this->siteId);
		$langs = array();
		$langs["null"] = TextHandler::getText("language_null");
		foreach($siteLangs as $key => $value) {
			$langs[$key] = $value;
		}
			
		return $langs;
	}


	/**
	 * Bizonyos dolgokat nem tárolhatunk soha - például a jogokat, brand kapcsolatokat!
	 */
	public function __sleep()
	{
		$props = ClassUtil::getPropertyNames("SiteUser");
		$removeProps = array("_calcRights", "_rightLabelPostfix");
		$props = array_diff($props, $removeProps);
		// Log::debug("----- sleep: ".FunctionLibrary::arrayToString($props));
			
		return $props;
	}

	public function __wakeup()
	{
	}


	private function __________permissions(){
	}


	protected function calculateRights() {
			
		if(!is_null($this->_calcRights))
		return;
			
		$this->_calcRights = SiteUser::getCalculatedRights($this);
	}


	/**
	 * Ez a metódus megkapja a db-ben tárolt SiteUser jogmaszkot, és ebből visszaad egy olyan, teljes jogmaszkot,
	 * ami már figyelembe veszi a jogok közti összefüggéseket
	 *
	 * @param SiteUser $user a user rekord
	 * @return int teljes jogmaszk, ami már betartja a jogok közti szabályokat
	 */
	public static function getCalculatedRights($user) {

		// ezeknek semmilyen joguk sincsen!
		if($user->type == SiteUser::TYPE_NEWREG) {
			return 0;
		}
			
		$dbRights = $user->rights;
			
		// root-nak minden joga megvan!
		if(($dbRights & USERRIGHT_ROOT) > 0) {
			return (SiteUser::getAllUserRights() | USERRIGHT_ROOT);
		}

		// ez a jog már tutira nem lesz ettől kezdve a getAllUserRights()-ban
		$exceptMask = USERRIGHT_ROOT;
			
		// ha superuser, akkor minden további joga megvan
		if(($dbRights & USERRIGHT_SUPERUSER) > 0) {
			return SiteUser::getAllUserRights($exceptMask);
		}
			
		// superuser jog sem lehet már ettől kezdve a getAllUserRights()-ban
		$exceptMask |= USERRIGHT_SUPERUSER;

			
		return USERRIGHT_REGISTERED;
	}


	/**
	 * Minden jogot beállít a maszkban ami fel van véve - kivéve a megadottakat
	 *
	 * @param int $exceptTheeseMask azon jogok bitjei magasak benne, amiket kapcsoljon ki!
	 * @return int a jogmaszk
	 */
	protected static function getAllUserRights($exceptTheeseMask = 0) {

		// minden jogot összerakunk - kivév ROOT
		$rights = USERRIGHT_SUPERUSER + USERRIGHT_REGISTERED;
			
		// végül lekapcsoljuk belőle azon biteket, amiket nem kértek
		$rights &= (~$exceptTheeseMask);
			
		return $rights;
	}



	/**
	 * Megmondja, hogy a usernek van-e adott joga. Alapból ez a kalkulált jogmaszon fut le - kivéve ha azt kéred hogy a db jogokon menjen purén.
	 * Ezzel viszont óvatosan!
	 *
	 * @param int $right valamelyik RIGHT_xxx konstans a constants.php-ból - szigorúan 1 db!
	 * @param boolean $useDBPureRights ha true akkor a db pure jogmaszkot használja - óvatosan vele!
	 *
	 * @return boolean true ha van joga, false ha nem van!
	 */
	public function hasRight($right, $useDBPureRights = false) {
			
		if(!$useDBPureRights)
		{
			$this->calculateRights();
			return (($this->_calcRights & $right) > 0);
		}
		else
		return (($this->rights & $right) > 0);
	}


	public function setRight($rightBit) {
		if(!$this->hasRight($rightBit, true)) {
			$this->setRights($this->rights | $rightBit);
		}
	}

	public function delRight($rightBit) {
		if($this->hasRight($rightBit, true)) {
			$newRight = $this->rights & (~$rightBit);
			$this->setRights($newRight);
		}
	}



	/**
	 * Visszaadja a user jogmaszkját. Alapból ez a kalkulált jogmaszon fut le - kivéve ha azt kéred hogy a db jogokon menjen purén.
	 * Ezzel viszont óvatosan!
	 *
	 * @param boolean $useDBPureRights ha true akkor a db pure jogmaszkot használja - óvatosan vele!
	 *
	 * @return int a jogmaszk
	 */
	public function getRights($useDBPureRights = false) {
			
		if(!$useDBPureRights)
		{
			$this->calculateRights();
			return $this->_calcRights;
		}
		else
		return $this->rights;
	}



	private function __________dbObject_customized(){
	}

	/**
	 * Ellenőrizzük a mezőinket, hogy oké legyen minden!
	 * A hibákat egy tömbben lehet visszaadni!
	 *
	 * FONTOS!!! A BBTrackedDBObject átköti a delete() metódust lényegében egy save()-re. Ami meg majd meghívja ezt ugyebár...
	 * Tehát figyelni kell arra, hogy ha ez a fake törölt állapot áll elő, akkor már ne akadékoskodjunk!
	 *
	 * @return array nyelvesített hibaüzenetek tömbje vagy null ha mehet a save!
	 * @see lib/classes/db/mapping/DBObject#checkFields()
	 */
	public function checkFields() {
			
		$errors = parent::checkFields();
		if(is_null($errors))
		$errors = array();
			
		if(!$this->isNew) {
			// ellenőrzünk!

			// ha bármi meghal, akkor nem fogadhatjuk el a mezőket, mert nem garantálhatjuk hogy nem
			// zúzzuk szét a db-t!
			try {
				if(TextUtil::isStringEmpty($this->email))
					array_push($errors, TextHandler::getText("obj_SiteUser_emailempty"));
				elseif(!FunctionLibrary::checkEmailSyntax($this->email))
					array_push($errors, TextHandler::getText("obj_SiteUser_bademailsyntax"));
				else {
					// ellenőrizni kell, hogy nincs-e már használatban a mail
					$filter = new DBQueryFilter();
					$filter->addComponent("email", DBQueryFilter::OP_EQUALS, $this->email);
					if(!$this->isNew)
						// magunkat nem kérjük el, köszi
						$filter->addComponent("id", DBQueryFilter::OP_NOT_EQUALS, $this->id);
					$recs = GeneralDBHelper::getTableRowsFiltered("siteuser", $filter, null, null, array("id"));
					if(!empty($recs))
						array_push($errors, TextHandler::getText("obj_SiteUser_emailexists"));
				}
										
			} catch (Exception $e) {
				$msg = "failed to check fields of SiteUser object, exception occured: ".Log::getExceptionInfo($e);
				Log::error($msg);
				MailHelper::sendAdminMail("SiteUser check failed", $msg);
					
				$errors = array(TextHandler::getText("obj_check_fatalerr"));
			}
		}
			
		if(empty($errors)) return null;
		return $errors;
	}


	/**
	 * Mentés előtt pár mezőt rendbeteszünk
	 * @return array hibaüzenetek
	 */
	protected function onBeforeSave() {
			
		$errors = parent::onBeforeSave();
			
		if(TextUtil::isStringEmpty($this->name))
			$this->name = null;

		return $errors;
	}



	private function __________query_db(){
	}



	/**
	 * SiteUser objektum lekeresése email szerint - ami ugye egyedi...
	 *
	 * @param $email
	 * @param $dbColumnNames
	 * @param $cacheControl
	 * @return SiteUser
	 */
	public static function getSiteUserWithEmail($email, $dbColumnNames = null, $cacheControl = null) {
			
		if(empty($email)) return null;
			
		$filter = new DBQueryFilter();
		$filter->addComponent("email", DBQueryFilter::OP_EQUALS, $email);

		$dbObject = null;
		$dbObjects =& DBSiteUser::getObjects($filter, null, null, $dbColumnNames, $cacheControl);
		if(!empty($dbObjects)) {
			if(count($dbObjects) > 1) {
				// ez gáz, azért egy warningot megér...
				$msg = "more than one SiteUser record returned for email='$email'... returning no object!";
				Log::error($msg);
				MailHelper::sendAdminMail("db inconsistency found", $msg);
			}
			else
			$dbObject = $dbObjects[0];
		}

		return $dbObject;
	}


	/**
	 * SiteUser objektum lekeresése username szerint - ami ugye egyedi...
	 *
	 * @param $username
	 * @param $dbColumnNames
	 * @param $cacheControl
	 * @return SiteUser
	 */
	public static function getSiteUserWithUsername($username, $dbColumnNames = null, $cacheControl = null) {
		return SiteUser::getSiteUserWithEmail($username, $dbColumnNames, $cacheControl);
	}


	/**
	 * A SiteUser rekord legszűkebb részhalmazát nyalja fel, ami ahhoz kell hogy userként használjuk!
	 * Ezek a lekérdezések alapból nem cache-elődnek soha a req-resp loop cache-ben, mivel az összeütközne a SiteUser
	 * cache cuccal.
	 * Viszont ha a cache-ben van már full SiteUser rekord, akkor azt fogja használni - kivéve ha a $cacheControl-lal mindezt
	 * felülírod...
	 *
	 * @param int $id az objektum azonosítója
	 * @return SiteUser az objektum, vagy null ha nincs ilyen
	 * @throws Exception hiba esetén nyelvesített exception megy
	 * @see BBTrackedDBObject::getObjectWithKey()
	 */
	public static function getUserWithId($id, $cacheControl = null) {
		if(is_null($cacheControl))
		$cacheControl = DBObject::CACHECONTROL_READ_ONLY;
		$dbObject = DBSiteUser::getObjectWithKey($id, ConstHandler::get('SITEUSER_QUERY_FIELDS'), $cacheControl);
		return $dbObject;
	}

	/**
	 * Adott userek felolvasása id-halmaz alapján.
	 *
	 * A SiteUser rekord legszűkebb részhalmazát nyalja fel, ami ahhoz kell hogy userként használjuk!
	 * Ezek a lekérdezések alapból nem cache-elődnek soha a req-resp loop cache-ben, mivel az összeütközne a SiteUser
	 * cache cuccal.
	 * Viszont ha a cache-ben van már full SiteUser rekord, akkor azt fogja használni - kivéve ha a $cacheControl-lal mindezt
	 * felülírod...
	 *
	 * @param array $ids a user id-k tömbje
	 * @return array SiteUser objektumok tömbje, üres tömb ha nincs egy sem
	 * @throws Exception hiba esetén nyelvesített exception megy
	 */
	public static function &getUsersWithIds($ids, $cacheControl = null) {
		if(is_null($cacheControl))
		$cacheControl = DBObject::CACHECONTROL_READ_ONLY;

		if(empty($ids))
		{
			$objects = array();
			return $objects;
		}

		$filter = new DBQueryFilter();
		$filter->addComponent("id", DBQueryFilter::OP_IN, $ids);
		$objects =& DBSiteUser::getObjects($filter, null, null, ConstHandler::get('SITEUSER_QUERY_FIELDS'), $cacheControl);
		return $objects;
	}


	/**
	 * A SiteUser rekord legszűkebb részhalmazát nyalja fel az amúgy unique e-mail mező segítségével, ami ahhoz kell hogy userként használjuk!
	 * Ezek a lekérdezések nem cache-elődnek soha a req-resp loop cache-ben, mivel az összeütközne a SiteUser
	 * cache cuccal.
	 * Viszont ha a cache-ben van már full SiteUser rekord, akkor azt fogja használni!
	 *
	 * @param string $email az email cím
	 * @return SiteUser az objektum, vagy null ha nincs ilyen
	 * @throws Exception hiba esetén nyelvesített exception megy
	 */
	public static function getUserWithEmail($email) {
		return SiteUser::getSiteUserWithEmail($email, ConstHandler::get('SITEUSER_QUERY_FIELDS'), DBObject::CACHECONTROL_READ_ONLY);
	}

	/**
	 * A SiteUser rekord legszűkebb részhalmazát nyalja fel az amúgy unique username mező segítségével, ami ahhoz kell hogy userként használjuk!
	 * Ezek a lekérdezések nem cache-elődnek soha a req-resp loop cache-ben, mivel az összeütközne a SiteUser
	 * cache cuccal.
	 * Viszont ha a cache-ben van már full SiteUser rekord, akkor azt fogja használni!
	 *
	 * @param string $username az email cím
	 * @return SiteUser az objektum, vagy null ha nincs ilyen
	 * @throws Exception hiba esetén nyelvesített exception megy
	 */
	public static function getUserWithUsername($username) {
		return SiteUser::getSiteUserWithUsername($username, ConstHandler::get('SITEUSER_QUERY_FIELDS'), DBObject::CACHECONTROL_READ_ONLY);
	}

}
?>